1 module hunt.templates.match;
2 
3 import std.regex;
4 import std.string;
5 import std.traits;
6 import std.stdio;
7 import std.conv;
8 import std.algorithm.sorting;
9 
10 import hunt.templates.rule;
11 
12 class Match
13 {
14 	string _pattern;
15 public:
16 	this()
17 	{
18 	}
19 
20 	this(string pattern)
21 	{
22 		_pattern = pattern;
23 	}
24 
25 	void set_pattern(string pat)
26 	{
27 		_pattern = pat;
28 	}
29 
30 	@property string pattern()
31 	{
32 		return _pattern;
33 	}
34 
35 	string str(int i = 0)
36 	{
37 		return string.init;
38 	}
39 
40 	string prefix()
41 	{
42 		writeln("-----debug------", __LINE__);
43 		return string.init;
44 	}
45 
46 	string suffix()
47 	{
48 		writeln("-----debug------", __LINE__);
49 		return string.init;
50 	}
51 
52 	size_t position()
53 	{
54 		writeln("-----debug------", __LINE__);
55 		return 0;
56 	}
57 
58 	size_t end_position()
59 	{
60 		writeln("-----debug------", __LINE__);
61 		return 0;
62 	}
63 
64 	bool found()
65 	{
66 		//writeln("-----debug------", __LINE__);
67 		return false;
68 	}
69 }
70 
71 class MatchType(T, R = string) : Match
72 {
73 	T type_;
74 	RegexMatch!(R) _allm;
75 	Captures!(R) _firstm;
76 	size_t offset_ = 0;
77 public:
78 	this()
79 	{
80 		super();
81 	}
82 
83 	this(size_t cur, string pattern = string.init)
84 	{
85 		super(pattern);
86 		offset_ = cur;
87 	}
88 
89 	void setMatchResult(ref RegexMatch!(R) rm)
90 	{
91 		_allm = rm;
92 	}
93 
94 	@property RegexMatch!(R) match()
95 	{
96 		return _allm;
97 	}
98 
99 	void setMatchFirst(ref Captures!(R) fm)
100 	{
101 		_firstm = fm;
102 	}
103 
104 	@property Captures!(R) firstMatch()
105 	{
106 		return _firstm;
107 	}
108 
109 	void set_type(T type)
110 	{
111 		type_ = type;
112 	}
113 
114 	@property T type() const
115 	{
116 		return type_;
117 	}
118 
119 	@property bool empty()
120 	{
121 		return _allm.empty && _firstm.empty;
122 	}
123 
124 	override bool found()
125 	{
126 		return !empty;
127 	}
128 
129 	@property size_t size()
130 	{
131 		return _allm.front.length;
132 	}
133 
134 	override string str(int i = 0)
135 	{
136 		if (i >= _allm.front.length)
137 			return string.init;
138 		return _allm.front[i];
139 	}
140 
141 	override string prefix()
142 	{
143 		return _allm.front.pre;
144 	}
145 
146 	override string suffix()
147 	{
148 		return _allm.front.post;
149 	}
150 
151 	override size_t position()
152 	{
153 		return offset_ + prefix.length;
154 	}
155 
156 	override size_t end_position()
157 	{
158 		return position() + str(0).length;
159 	}
160 
161 }
162 
163 class MatchClosed
164 {
165 public:
166 	Match _open_match, _close_match;
167 
168 	this()
169 	{
170 		_open_match = new Match();
171 		_close_match = new Match();
172 	}
173 
174 	this(Match open_match, Match close_match)
175 	{
176 		_open_match = open_match;
177 		_close_match = close_match;
178 	}
179 
180 	size_t position()
181 	{
182 		return _open_match.position();
183 	}
184 
185 	size_t end_position()
186 	{
187 		return _close_match.end_position();
188 	}
189 
190 	size_t length()
191 	{
192 		return _close_match.end_position() - _open_match.position();
193 	}
194 
195 	bool found()
196 	{
197 		return _open_match.found() && _close_match.found();
198 	}
199 
200 	string prefix()
201 	{
202 		return _open_match.prefix();
203 	}
204 
205 	string suffix()
206 	{
207 		return _close_match.suffix();
208 	}
209 
210 	string outer()
211 	{
212 		return _open_match.str(0) ~ _open_match.suffix()[0 .. _close_match.end_position() - _open_match.end_position()];
213 	}
214 
215 	string inner()
216 	{
217 		//writeln("close pos : ", _close_match.position(), "    open end : ",
218 		//		_open_match.end_position());
219 		return _open_match.suffix()[0 .. _close_match.position() - _open_match.end_position()];
220 	}
221 }
222 
223 class RegexObj
224 {
225 
226 	string _pattern;
227 
228 public:
229 	this(string pattern)
230 	{
231 		_pattern = pattern;
232 	}
233 
234 	@property string pattern()
235 	{
236 		return _pattern;
237 	}
238 
239 	static auto search(string input, string pattern, size_t pos = 0)
240 	{
241 		MatchType!(string) m = new MatchType!(string)(pos, pattern);
242 		auto res = matchAll(pos > 0 ? input[pos .. $] : input, regex(pattern));
243 		m.setMatchResult(res);
244 		return m;
245 	}
246 
247 	static auto search_first(string input, string pattern, size_t pos = 0)
248 	{
249 		MatchType!(string) m = new MatchType!(string)(pos, pattern);
250 		auto res = matchFirst(pos > 0 ? input[pos .. $] : input, regex(pattern));
251 		m.setMatchFirst(res);
252 		return m;
253 	}
254 
255 	static auto search_all(string input, size_t pos = 0)
256 	{
257 		MatchType!(Delimiter) m = new MatchType!(Delimiter)(pos);
258 		string[] patterns;
259 		Delimiter[int] sort_key;
260 		int i = 1;
261 		foreach (Delimiter k, string v; regex_map_delimiters)
262 		{
263 			patterns ~= v;
264 			sort_key[i] = k;
265 			i++;
266 		}
267 		auto res = matchAll(pos > 0 ? input[pos .. $] : input, regex(patterns));
268 		m.setMatchResult(res);
269 		if (!res.empty)
270 		{
271 			auto idx = res.front.whichPattern;
272 			//writeln("--patterns :",patterns);
273 
274 			if (idx in sort_key)
275 			{
276 				m.set_type(sort_key[idx]);
277 				m.set_pattern(regex_map_delimiters[m.type]);
278 				//writeln("--seach first pattern :", m.pattern);
279 			}
280 		}
281 
282 		return m;
283 	}
284 
285 	static auto match(T)(string input, string[T] map, size_t pos = 0)
286 	{
287 		auto keys = map.keys;
288 		sort!("a < b")(keys);
289 		foreach(e;keys)
290 		{
291 			auto v =map[e];
292 			auto res = matchAll(pos > 0 ? input[pos .. $] : input, regex(v));
293 			if (!res.empty)
294 			{
295 				MatchType!(T) mt = new MatchType!(T)(pos, v);
296 				mt.setMatchResult(res);
297 				mt.set_type(e);
298 				//writeln("--match pattern :", v, "   --->type : ", e);
299 				return mt;
300 			}
301 		}
302 		//writeln("--no match pattern ");
303 		MatchType!(T) mt = new MatchType!(T)(pos);
304 		return mt;
305 	}
306 
307 	static MatchClosed search_closed_on_level(string input, string regex_statement,
308 			string regex_level_up, string regex_level_down, string regex_search, Match open_match)
309 	{
310 
311 		int level = 0;
312 		size_t current_position = open_match.end_position();
313 		auto match_delimiter = search(input, regex_statement, current_position);
314 		while (match_delimiter.found())
315 		{
316 			//writeln("---current_position : ",current_position);
317 			//writeln("---current  delimiter: ",match_delimiter.str(0));
318 			current_position = match_delimiter.end_position();
319 			string inner = match_delimiter.str(1);
320 			if (search(inner, regex_search).found() && level == 0)
321 			{
322 				break;
323 			}
324 			if (search(inner, regex_level_up).found())
325 			{
326 				level += 1;
327 			}
328 			else if (search(inner, regex_level_down).found())
329 			{
330 				level -= 1;
331 			}
332 
333 			if (level < 0)
334 			{
335 				//writeln("-----level<0------", __LINE__);
336 				return new MatchClosed();
337 			}
338 			match_delimiter = search(input, regex_statement, current_position);
339 		}
340 		//writeln("-----close match ---end pos---",match_delimiter.end_position(),"---level : ",level);
341 		return new MatchClosed(open_match, match_delimiter);
342 	}
343 
344 	static MatchClosed search_closed(string input, string regex_statement,
345 			string regex_open, string regex_close, Match open_match)
346 	{
347 		return search_closed_on_level(input, regex_statement, regex_open,
348 				regex_close, regex_close, open_match);
349 	}
350 }